/*!
 * This CUDA class is a kNN implementation from a GitHub repo
 * \link https://github.com/vincentfpgarcia/kNN-CUDA
 */

namespace ORNL {
    bool knn_cuda_global(const float * ref,
                         int           ref_nb,
                         const float * query,
                         int           query_nb,
                         int           dim,
                         int           k,
                         float *       knn_dist,
                         int *         knn_index);


    /**
     * For each input query point, locates the k-NN (indexes and distances) among the reference points.
     * This implementation uses texture memory for storing reference points  and memory to store query points.
     *
     * @param ref        refence points
     * @param ref_nb     number of reference points
     * @param query      query points
     * @param query_nb   number of query points
     * @param dim        dimension of points
     * @param k          number of neighbors to consider
     * @param knn_dist   output array containing the query_nb x k distances
     * @param knn_index  output array containing the query_nb x k indexes
     */
    bool knn_cuda_texture(const float * ref,
                          int           ref_nb,
                          const float * query,
                          int           query_nb,
                          int           dim,
                          int           k,
                          float *       knn_dist,
                          int *         knn_index);


    /**
     * For each input query point, locates the k-NN (indexes and distances) among the reference points.
     * Using cuBLAS, the computation of the distance matrix can be faster in some cases than other
     * implementations despite being more complex.
     *
     * @param ref        refence points
     * @param ref_nb     number of reference points
     * @param query      query points
     * @param query_nb   number of query points
     * @param dim        dimension of points
     * @param k          number of neighbors to consider
     * @param knn_dist   output array containing the query_nb x k distances
     * @param knn_index  output array containing the query_nb x k indexes
     */
    bool knn_cublas(const float * ref,
                    int           ref_nb,
                    const float * query,
                    int           query_nb,
                    int           dim,
                    int           k,
                    float *       knn_dist,
                    int *         knn_index);

}
